import java.util.concurrent.CountDownLatch;

/**
 * StaticIdentifier 静态字段和静态方法 用static修饰的字段，称为静态字段：static field。
 * 实例字段在每个实例中都有自己的一个独立“空间”，但是静态字段只有一个共享“空间”，所有实例都会共享该字段
 */
public class StaticIdentifier {

    public static void main(String[] args) {
        Person xiaowang = new Person();
        xiaowang.name = "xiaowang";
        xiaowang.age = 12;
        xiaowang.number = 1;

        System.out.println(xiaowang.number);// 1

        Person xiaoli = new Person();
        xiaoli.name = "xiaoli";
        xiaoli.age = 14;
        xiaoli.number = 2;
        Person.number = 3;
        System.out.println(xiaowang.number);// 2
        // 改变了xiaoli的number字段之后,打印xiaowang的number字段发现,xiaowang的number字段也发生了改变
        // 说明了所有的实例对象共享static字段,一个对象的字段改变,其他的对象跟着改变
        // 可以用Person.number = 3;的方式访问number字段,因为number字段是属于Person类的,不属于任何一个实例对象
        // 因此，不推荐用实例变量.静态字段去访问静态字段，因为在Java程序中，实例对象并没有静态字段。在代码中，实例对象能访问静态字段只是因为编译器可以根据实例类型自动转换为类名.静态字段来访问静态对象。

        Person.setNumber(22);
        System.out.println(Person.number);

        // 练习
        PersonStaticTest p1 = new PersonStaticTest();
        System.out.println(PersonStaticTest.COUNT);
        PersonStaticTest p2 = new PersonStaticTest();
        System.out.println(PersonStaticTest.COUNT);
        PersonStaticTest p3 = new PersonStaticTest();
        PersonStaticTest p4 = new PersonStaticTest();
        PersonStaticTest p5 = new PersonStaticTest();
        System.out.println(PersonStaticTest.COUNT);

    }
}

class Person {
    public String name;
    public int age;

    // 定义静态字段number
    public static int number;

    // 定义静态方法 : 静态方法访问不需要使用实例对象,直接用类名就可以调用 (Person.setNumber(99));
    // 因为静态方法属于class而不属于实例，因此，静态方法内部，无法访问this变量，也无法访问实例字段，它只能访问静态字段。
    // 通过实例变量也可以调用静态方法，但这只是编译器自动帮我们把实例改写成类名而已。
    public static void setNumber(int value) {
        number = value;
    }
}

// 定义一个接口类 PersonInterface
// 接口中可以声明静态字段,并且只能是final类型
// 实际上，因为interface的字段只能是public static final类型，所以我们可以把这些修饰符都去掉
interface PersonInterface {
    // public static final int MALE = 1;
    // public static final int FEMALE = 2;

    // 编译器会自动为字段前加上 public static final
    int MALE = 1;
    int FEMALE = 2;

}

// 练习: 给Person类增加一个静态字段count和静态方法getCount，统计实例创建的个数
class PersonStaticTest {
    static int COUNT = 0; // 统计一共创建了多少个实例对象

    // 获取静态字段COUNT
    static int getCount() {
        return COUNT;
    }

    // 自定义构造方法,每创建一个实例,就把静态字段COUNT + 1
    public PersonStaticTest() {
        PersonStaticTest.COUNT += 1;
    }
}